/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package view;

import com.sun.lwuit.Command;
import com.sun.lwuit.Form;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.layouts.BorderLayout;
import com.sun.lwuit.list.DefaultListModel;
import core.DistrictsManager;
import core.DriverManager;
import core.OrderManager;
import core.ScreenEngine;
import core.Settings;
import core.TaxiMIDlet;
import datamodel.DriverState;
import network.Connection;
import network.PacketBuilder;
import network.packets.AdResponce;
import network.packets.ChangeDriverStateResponce;
import network.packets.DistrictsListResponce;
import network.packets.DistrictsUpdateServerTimeResponce;
import network.packets.MyInfoResponce;
import network.packets.OrdersListResponce;
import network.packets.Packet;
import view.additional.CellItem;
import view.additional.FunctionsMaskListener;
import view.additional.ThumbList;
import view.additional.TickerRenderer;
import view.commands.BackCommand;

/**
 *
 * @author Kvest
 */
public class FunctionsForm extends Form implements DriverManager.DriverStateChangedListener, FunctionsMaskListener
{
    //Данные для маски
    //Районы, Заявки, "Смена состояния", Завершить смену, Диспетчерская, Объявление, Мои предвар. Заявки, Мои данные, Выход
    private static final int DISTRICTS_MASK = 1;
    private static final int ORDERS_MASK = 2;
    private static final int DRIVER_STATE_MASK = 4;
    private static final int CLOSE_RELAY_MASK = 8;
    private static final int DISPETCHING_OFFICE_MASK = 16;
    private static final int ADVERTISEMENT_MASK = 32;
    private static final int MY_PREORDERS_MASK = 64;
    private static final int MY_INFO_MASK = 128;
    private static final int EXIT_MASK = 256;
    private static final int DISTRICTS_SECOND_MASK = 512;
    
    private static final int SELECT_COMMAND_ID = 1;
    
    private static final int DISTRICTS_ID = 0;
    private static final int ORDERS_ID = 1;
    private static final int DRIVER_STATE_ID = 2;
    private static final int CLOSE_RELAY_ID = 3;
    private static final int DISPETCHING_OFFICE_ID = 4;
    private static final int ADVERTISEMENT_ID = 5;
    private static final int MY_PREORDERS_ID = 6;
    private static final int MY_INFO_ID = 7;
    private static final int EXIT_ID = 8;
    private static final int INFO_ID = 9;
    private static final int MESSAGES_ID = 10;
    private static final int DISTRICTS_SECOND_ID = 11;
    
//    private static final int DRIVER_STATE_POSITION = 2;
    
    private ThumbList items;
    private CellItem districtsItem;
    private CellItem ordersItem;
    private CellItem stateItem;
    private CellItem closeRelayItem;
    private CellItem dispetcheringItem;
    private CellItem advertismenetItem;
    private CellItem myPreordersItem;
    private CellItem myInfoItem;
    private CellItem exitItem;
    private CellItem infoItem;
    private CellItem messagesItem; 
    private CellItem districtsSecondItem;
    private Command select;
    
    private DistrictsForm districtsForm;
    private OrdersListForm ordersListForm;
    private DispetchingOfficeForm dispetchingOfficeForm;
    private AdForm adForm;
    private MyInfoForm myInfoForm;
    private InfoForm infoForm;
    private MessagesListForm messagesList;
    
    public FunctionsForm()
    {
        super("functions");
        districtsForm = null;
        ordersListForm = null;
        
        TaxiMIDlet.getMidlet().setFunctionsMaskListener(this);
        
        init();
    }
    
    private void init()
    {
        setLayout(new BorderLayout());
        setScrollable(false);
        
        //Создаем список
        items = new ThumbList();
        items.setSelectCommandText("...");
        items.setFixedSelection(ThumbList.FIXED_NONE_CYCLIC);
        TickerRenderer render = new TickerRenderer();
        items.setRenderer(render);
        
        initItems();
        addComponent(BorderLayout.CENTER, items);
        
        //Команды
        select = new Command("select",SELECT_COMMAND_ID)
        {
            public void actionPerformed(ActionEvent evt)
            {
                selectAction();
                
                evt.consume();
            }
        };
        addCommand(select);
        
        items.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent evt) 
            {
                select.actionPerformed(evt);
            }
        });
        
        addCommand(new BackCommand());

        DriverManager.getManager().setDriverNextStateChangedListener(this);
    }
    
    public void show()
    {
        setNextState();
        
        super.show();
    }
    
    private void setNextState() 
    {
        DriverState nextState = DriverManager.getManager().getNextState();
        stateItem.setText(nextState.getName());
        
//        if (nextState.getId() == DriverState.EMPTY_STATE_ID)
//        {
//            if (items.getModel().getItemAt(DRIVER_STATE_POSITION) == stateItem)
//            {
//                items.getModel().removeItem(DRIVER_STATE_POSITION);
//            }
//        }
//        else
//        {
//            stateItem.setText(nextState.getName());
//            
//            if (items.getModel().getItemAt(DRIVER_STATE_POSITION) != stateItem)
//            {
//                items.getModel().addItemAtIndex(stateItem, DRIVER_STATE_POSITION);
//            }
//        }
    }
    
    private void initItems()
    {
        districtsItem = new CellItem(DISTRICTS_ID, "districts");
        ordersItem = new CellItem(ORDERS_ID, "orders");
        stateItem = new CellItem(DRIVER_STATE_ID, DriverManager.getManager().getNextState().getName());
        closeRelayItem = new CellItem(CLOSE_RELAY_ID, "close_relay");
        dispetcheringItem = new CellItem(DISPETCHING_OFFICE_ID, "dispetching_office");
        messagesItem = new CellItem(MESSAGES_ID, "messages");
        advertismenetItem = new CellItem(ADVERTISEMENT_ID, "advertisement");
        myPreordersItem = new CellItem(MY_PREORDERS_ID, "my_preorders");
        myInfoItem = new CellItem(MY_INFO_ID, "my_info"); 
        exitItem = new CellItem(EXIT_ID, "exit");
        infoItem = new CellItem(INFO_ID, "info");
        districtsSecondItem = new CellItem(DISTRICTS_SECOND_ID, "districts");
        
        maskChanged(Settings.getSettings().getFunctionsMask());
    }
    
    private void selectAction()
    {
        CellItem selected = (CellItem)items.getSelectedItem();
        
        switch(selected.getId())
        {
            case DISTRICTS_ID : requestDistricts(); break;
            case ORDERS_ID : requestOrders(); break;
            case DRIVER_STATE_ID : changeDriverState(); break;
            case CLOSE_RELAY_ID : doCloseRelay(); break;
            case DISPETCHING_OFFICE_ID : showDispetchingOffice(); break;
            case ADVERTISEMENT_ID: requestAdvertisement(); break;
            //case MY_PREORDERS_ID:  break;
            case MY_INFO_ID: requestMyInfo(); break;
            case EXIT_ID : doExit(); break;
            case INFO_ID : showInfoForm(); break;
            case MESSAGES_ID : showMessagesList(); break;  
            case DISTRICTS_SECOND_ID : requestDistricts(); break;
        }
    }

    public void maskChanged(int mask)
    {
        ((DefaultListModel)items.getModel()).removeAll();
        if ((mask & DISTRICTS_MASK) == DISTRICTS_MASK)
        {
            items.addItem(districtsItem);
        }
        if ((mask & ORDERS_MASK) == ORDERS_MASK)
        {
            items.addItem(ordersItem);
        }
        if ((mask & DRIVER_STATE_MASK) == DRIVER_STATE_MASK)
        {
            items.addItem(stateItem);
        }
        if ((mask & CLOSE_RELAY_MASK) == CLOSE_RELAY_MASK)
        {
            items.addItem(closeRelayItem);
        }
        if ((mask & DISTRICTS_SECOND_MASK) == DISTRICTS_SECOND_MASK)
        {
            items.addItem(districtsSecondItem);
        }
        if ((mask & DISPETCHING_OFFICE_MASK) == DISPETCHING_OFFICE_MASK)
        {
            items.addItem(dispetcheringItem);
        }
        items.addItem(messagesItem);
        if ((mask & ADVERTISEMENT_MASK) == ADVERTISEMENT_MASK)
        {
            items.addItem(advertismenetItem);
        }
        if ((mask & MY_PREORDERS_MASK) == MY_PREORDERS_MASK)
        {
            //ToDo Kvest
            //items.addItem(myPreordersItem);
        }
        if ((mask & MY_INFO_MASK) == MY_INFO_MASK)
        {
            items.addItem(myInfoItem);
        }
        items.addItem(infoItem);
        if ((mask & EXIT_MASK) == EXIT_MASK)
        {
            items.addItem(exitItem);
        }
                
        if (isVisible())
        {
            repaint();
        }
    }
    
    private void requestDistricts()
    {
        DistrictsManager districtsManager = DistrictsManager.getDistrictsManager();
        if (districtsManager.getServerUpdateTime() == DistrictsManager.UNKNOWN_TIME)
        {
            //Отображаем форму прогресса
            ScreenEngine.getEngine().push(new ProgressForm());
            
            //Регистрируем обработчик
            registerDistrictsUpdateServerTimeListener();
            
            //Генерируем и отправляем запрос
            byte[] data = PacketBuilder.createDistrictsUpdateServerTime();
            Connection.getConnection().send(data);
        }
        else if (districtsManager.getServerUpdateTime() > districtsManager.getLatsUpdateTime())
        {
            //Отображаем форму прогресса
            ScreenEngine.getEngine().push(new ProgressForm());
            
            //Регистрируем обработчик
            registerDistrictsListListener();        
                    
            //Генерируем и отправляем запрос
            byte[] data = PacketBuilder.createDistrictsListRequest();
            Connection.getConnection().send(data);
        }
        else
        {
            //Отображаем форму районов
            showDistricts();
        }
    }
    
    private void registerDistrictsUpdateServerTimeListener()
    {
        Connection.getConnection().setPacketListener(Packet.DISTRICTS_UPDATE_SERVER_TIME_RESPONCE, new Connection.PacketNotifier() 
        {
            public void incomingPacket(Packet packet) 
            {
                DistrictsUpdateServerTimeResponce responce = (DistrictsUpdateServerTimeResponce)packet;
                
                //Сохраняем время последнего обновления на сервере
                DistrictsManager.getDistrictsManager().setServerUpdateTime(responce.getUpdateTime());
                
                //Удаляем обработчик этого пакета
                Connection.getConnection().deletePacketListener(Packet.DISTRICTS_UPDATE_SERVER_TIME_RESPONCE);
                
                //Удаляем форму ожидания
                ScreenEngine.getEngine().popProgressForm(false);
                
                requestDistricts();
            }
        });
    }

    private void requestStatistic()
    {
        byte[] data = PacketBuilder.createDistrictsStatisticRequest();
        Connection.getConnection().send(data);
    }

    private void registerDistrictsListListener()
    {
        Connection.getConnection().setPacketListener(Packet.DISTRICTS_LIST_RESPONCE, new Connection.PacketNotifier() 
        {
            public void incomingPacket(Packet packet) 
            {
                DistrictsListResponce responce = (DistrictsListResponce)packet;
                
                
                //Сначала чистим старые районы
                DistrictsManager manager = DistrictsManager.getDistrictsManager();
                manager.clear();
                        
                //Сoхраняем время и районы
                manager.setLatsUpdateTime(responce.getListCreationTime());
                for (int i = 0; i < responce.getDistrictsCount(); ++i)
                {
                    manager.addDistrict(responce.getDistrict(i));
                }
                manager.save();
                
                //Удаляем обработчик этого пакета
                Connection.getConnection().deletePacketListener(Packet.DISTRICTS_LIST_RESPONCE);
                
                //Удаляем форму ожидания
                ScreenEngine.getEngine().popProgressForm(false);
                
                requestDistricts();
            }
        });
    }
    
    private void doCloseRelay()
    {
        //Отображаем форму прогресса
        ScreenEngine.getEngine().push(new ProgressForm());
        
        //Генерируем и отправляем запрос
        byte[] data = PacketBuilder.createCloseRelayRequest(DriverManager.getManager().getDriverID());
        boolean result = Connection.getConnection().send(data);
        
        //Переходим на главную форму
        ScreenEngine.getEngine().popTo(0);
        
        //Отображаем сообщение
        //MessageBox.showModeless("message", (result ? "relay_closed" : "relay_not_closed"));
    }
    
    private void showDispetchingOffice()
    {
        if (dispetchingOfficeForm == null)
        {
            dispetchingOfficeForm = new DispetchingOfficeForm();
        }
        
        ScreenEngine.getEngine().push(dispetchingOfficeForm);
    }

    private void requestAdvertisement()
    {
        //Отображаем форму прогресса
        ScreenEngine.getEngine().push(new ProgressForm());

        //Регистрируем обработчик
        registerAdListener();

        //Генерируем и отправляем запрос
        byte[] data = PacketBuilder.createAdRequest();
        Connection.getConnection().send(data);
    }

    private void requestMyInfo()
    {
        //Отображаем форму прогресса
        ScreenEngine.getEngine().push(new ProgressForm());

        //Регистрируем обработчик
        registerMyInfoListener();

        //Генерируем и отправляем запрос
        byte[] data = PacketBuilder.createMyInfoRequest(DriverManager.getManager().getDriverID());
        Connection.getConnection().send(data);
    }

    private void registerAdListener()
    {
        Connection.getConnection().setPacketListener(Packet.AD_RESPONCE, new Connection.PacketNotifier()
        {
            public void incomingPacket(Packet packet)
            {
                AdResponce responce = (AdResponce)packet;

                //Удаляем обработчик этого пакета
                Connection.getConnection().deletePacketListener(Packet.AD_RESPONCE);

                //Удаляем форму ожидания
                ScreenEngine.getEngine().popProgressForm(false);

                //Отображаем рекламу
                showAdForm(responce.getText());
            }
        });
    }

    private void registerMyInfoListener()
    {
        Connection.getConnection().setPacketListener(Packet.MY_INFO_RESPONCE, new Connection.PacketNotifier()
        {
            public void incomingPacket(Packet packet)
            {
                MyInfoResponce responce = (MyInfoResponce)packet;
                
                //Удаляем обработчик этого пакета
                Connection.getConnection().deletePacketListener(Packet.MY_INFO_RESPONCE);

                //Удаляем форму ожидания
                ScreenEngine.getEngine().popProgressForm(false);

                //Отображаем инфу о водителе
                showMyInfoForm(responce.getInfo());
            }
        });
    }

    private void changeDriverState()
    {
         //Отображаем форму прогресса
         ScreenEngine.getEngine().push(new ProgressForm());
            
         //Регистрируем обработчик
         registerDriverStateChangeListener(); 
         
         DriverManager driverManager = DriverManager.getManager(); 
         
         //Генерируем и отправляем запрос
         byte[] data = PacketBuilder.createChangeDriverStateRequest(driverManager.getDriverID(), driverManager.getNextState().getId());
         Connection.getConnection().send(data);
    }
    
    private void registerDriverStateChangeListener()
    {
        Connection.getConnection().setPacketListener(Packet.CHANGE_DRIVER_STATE_RESPONCE, new Connection.PacketNotifier() 
        {
            public void incomingPacket(Packet packet) 
            {
                ChangeDriverStateResponce responce = (ChangeDriverStateResponce)packet;

                //Меняем статусы водителя
                DriverManager.getManager().setCurrenntState(responce.getState());
                DriverManager.getManager().setNextState(responce.getNextState());
                
                //Настраиваем "Функции"
                Settings.getSettings().setFunctionsMask(responce.getFunctionsMask());
                maskChanged(responce.getFunctionsMask());
                
                //Удаляем обработчик этого пакета
                Connection.getConnection().deletePacketListener(Packet.CHANGE_DRIVER_STATE_RESPONCE);
                
                //Возвращаемся к главному меню
                ScreenEngine.getEngine().popTo(0);
            }
        });
    }
    
    private void showDistricts()
    {
        //Создаем форму списка районов, если она не создана
        if (districtsForm == null)
        {
            districtsForm = new DistrictsForm();

            //Запрашиваем статистику в фоне
            requestStatistic();
        }
        
        //Отображаем форму списка районов
        ScreenEngine.getEngine().push(districtsForm);
    }
    
    private void doExit()
    {
        //Отправляем пакет дисконекта
        ScreenEngine.getEngine().push(new ProgressForm());
        Connection.getConnection().send(PacketBuilder.createExitRequest(DriverManager.getManager().getDriverID()));

        //Останавливаем соединение
        Connection.getConnection().stop();

        //Закрываем приложение
        TaxiMIDlet.getMidlet().destroyApp(true);
    }
    
    private void showInfoForm()
    {
        if (infoForm == null)
        {
            infoForm = new InfoForm();
        }
        
        //Отображаем форму с информацией
        ScreenEngine.getEngine().push(infoForm);
    }
    
    private void showMessagesList()
    {
        if (messagesList == null)
        {
            messagesList = new MessagesListForm();
        }
        
        //Отображаем список сообщений
        ScreenEngine.getEngine().push(messagesList);
    }
    
    private void requestOrders()
    {
        //Если заявки уже запрашивали - просто отображаем список заявок
        if (!OrderManager.getManager().isOrdersGotten())
        {
            //Отображаем форму прогресса
            ScreenEngine.getEngine().push(new ProgressForm());
            
            //Регистрируем обработчик
            registerOrdersListListener();        
                    
            //Генерируем и отправляем запрос
            byte[] data = PacketBuilder.createOrdersListRequest();
            Connection.getConnection().send(data);
        }
        else
        {
            showOrdersList();
        }        
    }
    
    private void registerOrdersListListener()
    {
        Connection.getConnection().setPacketListener(Packet.ORDERS_LIST_RESPONCE, new Connection.PacketNotifier() 
        {
            public void incomingPacket(Packet packet) 
            {
                OrdersListResponce responce = (OrdersListResponce)packet;

                OrderManager orderManager = OrderManager.getManager();
                //Сохраняем заказы в менеджере
                for (int i = 0; i < responce.getOrdersCount(); ++i)
                {
                    orderManager.addOrder(responce.getOrder(i));
                }

                //Говорим что заказы уже были запрошены
                orderManager.setOrdersGotten(true);

                //Удаляем форму ожидания
                ScreenEngine.getEngine().popProgressForm(false);
                
                //Отображаем список заказов
                showOrdersList();
            }
        });
    }

    private void showAdForm(String adText)
    {
        if (adForm == null)
        {
            adForm = new AdForm();
        }

        //Устанавливаем текст объявлений
        adForm.setText(adText);

        //Отображаем форму объявлений
        ScreenEngine.getEngine().push(adForm);
    }

    private void showMyInfoForm(String info)
    {
        if (myInfoForm == null)
        {
            myInfoForm = new MyInfoForm();
        }

        //Устанавливаем текст инфы о водителе
        myInfoForm.setText(info);

        //Отображаем форму информации
        ScreenEngine.getEngine().push(myInfoForm);
    }

    private void showOrdersList()
    {
        //Создаем форму списка заявок
        if (ordersListForm == null)
        {
            ordersListForm = new OrdersListForm();
        }

        //Отображаем форму заявок
        ScreenEngine.getEngine().push(ordersListForm);
    }
    
    public void driverStateChanged(DriverState oldState, DriverState newState)
    {
        setNextState();

        items.repaint();
    }
}
